﻿// ------------------------------------------------------------------------
// 版权信息
// 版权归重庆虫儿飞科技有限公司所有。
// 所有权利保留。
// 官方网站：https://netokit.com
// 许可证信息
// Neto.Kit 项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
// 
// 使用条款
// 使用本代码应遵守相关法律法规和许可证的要求。
// 
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
// 
// 其他重要信息
// Neto.Kit 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// 有关 Neto.Kit 项目的其他详细信息，请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
// 
// 更多信息
// 请访问 https://netokit.com 获取更多关于 Neto.Kit 项目的许可证和版权信息。
// ------------------------------------------------------------------------

#region

using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc.Localization;
using Microsoft.Extensions.Localization;
using System.Globalization;

#endregion

namespace Neto.Localization;

/// <summary>
///     多语言扩展类
/// </summary>
[SuppressSniffer]
public static class LX
{
    /// <summary>
    ///     本地化日志文件夹
    /// </summary>
    public const string LogFloder = "Localization";

    /// <summary>
    ///     全球化本地化  缓存前缀
    /// </summary>
    private static readonly string Localization_CacheKeyPrefix = "Localization";


    /// <summary>
    ///     全球化本地化字典数据
    ///     <remarks>
    ///         <语种代码， 翻译字典>
    ///     </remarks>
    /// </summary>
    public static ConcurrentDictionary<string, Dictionary<string, string>> LocalizationDics = new();

    /// <summary>
    ///     生成缓存Key
    /// </summary>
    /// <param name="area">区域：默认 default</param>
    /// <param name="culture">区域码，默认en-US</param>
    /// <returns>完整的缓存Key</returns>
    public static string GetCacheKey(string area = "default", string culture = "en-US")
    {
        return $"{Localization_CacheKeyPrefix}_{area ?? ""}-{culture ?? ""}";
    }

    /// <summary>
    ///     获取本地化文本
    /// </summary>
    /// <param name="name">关键词</param>
    /// <param name="area">区域</param>
    /// <param name="culture">区域码，默认en-US</param>
    /// <param name="args">参数</param>
    /// <returns>本地化文本</returns>
    public static string Content(string name, string area = "", string culture = "en-US", params object[] args)
    {
        if (string.IsNullOrWhiteSpace(name)) return "";
        var dics = GetLocalizationDics(area, culture);
        // 如果找不到,且传入的区域不为空，则去默认区域找
        if (!dics.ContainsKey(name) && !string.IsNullOrWhiteSpace(area)) dics = GetLocalizationDics("", culture);

        var txt = name;
        if (dics.ContainsKey(name)) txt = dics[name];
        return string.Format(txt, args);
    }

    /// <summary>
    ///     获取本地化文本
    ///     区域码，默认为当前系统选择的，如果没找到，默认为：en-US
    /// </summary>
    /// <param name="name">关键词</param>
    /// <param name="arguments">参数</param>
    /// <returns>本地化文本</returns>
    public static string Content(string name, params object[] arguments)
    {
        var value = InvokeHelper.ExecuteReturn<string>(typeof(ILocalizationXEvent), LocalizationXEventConst.Translate,
            2,
            [name, arguments]);

        return value;
    }

    /// <summary>
    ///     获取全球化本地化字典数据
    /// </summary>
    /// <param name="culture">区域码</param>
    /// <param name="area">区域</param>
    /// <returns></returns>
    public static Dictionary<string, string> GetLocalizationDics(string culture, string area = null)
    {
        try
        {
            var dic = InvokeHelper.ExecuteReturn<Dictionary<string, string>>(typeof(ILocalizationXEvent),
                LocalizationXEventConst.GetCache, 2,
                [culture, area]);
            return dic ?? new Dictionary<string, string>();
        }
        catch (Exception e)
        {
            LogX.Error($"获取缓存 LX->GetLocalizationDics：{e.ToStringEx()}", LogFloder);
        }

        return new Dictionary<string, string>();
    }

    /// <summary>
    ///     设置全球化本地化翻译数据
    /// </summary>
    /// <param name="area">区域</param>
    /// <param name="culture">区域码</param>
    /// <param name="dic">数据字典</param>
    public static void SetCache(string area, string culture, Dictionary<string, string> dic)
    {
        LocalizationAddOrUpdate(area, culture, dic);
    }

    /// <summary>
    ///     刷新缓存
    /// </summary>
    public static void RefreshCache()
    {
        //执行注册的方法
        LocalizationLoadData();
    }

    /// <summary>
    ///     为指定区域和文化添加或更新本地化字典。
    /// </summary>
    /// <param name="area">区域名称，用于本地化区分不同的功能或模块。</param>
    /// <param name="culture">文化名称，用于指定语言和地区设置。</param>
    /// <param name="dic">包含本地化键值对的字典。</param>
    public static void LocalizationAddOrUpdate(string area, string culture, Dictionary<string, string> dic)
    {
        // 通过生成缓存键来调用另一个重载方法，以简化添加或更新过程
        //LocalizationAddOrUpdate(LX.GetCacheKey(area, culture), dic);
        try
        {
            InvokeHelper.Execute(typeof(ILocalizationXEvent), LocalizationXEventConst.SetCache, 3,
                [area, culture, dic]);
        }
        catch (Exception e)
        {
            LogX.Error($"设置缓存失败 LX->LocalizationAddOrUpdate：{e.ToStringEx()}", LogFloder);
        }
    }

    // /// <summary>
    // /// 添加或更新本地化字典到缓存中。
    // /// </summary>
    // /// <param name="cacheKey">用于缓存中标识本地化数据的键。</param>
    // /// <param name="dic">包含本地化键值对的字典。</param>
    // public static void LocalizationAddOrUpdate(string cacheKey, Dictionary<string, string> dic)
    // {
    //     // 使用字典添加或更新方法，如果键已存在，则用新的字典替换旧的。
    //     // LocalizationDics.AddOrUpdate(cacheKey, dic, (key, oldValue) => dic);
    //     
    //     InvokeHelper.Execute(typeof(ILocalizationXEvent), LocalizationXEventConst.SetCache, 0);
    // }


    /// <summary>
    ///     本地化初始化
    /// </summary>
    public static void LocalizationInit()
    {
        // //注册 加载数据
        InvokeHelper.Register(typeof(ILocalizationXEvent), LocalizationXEventConst.LoadData);
        // //注册翻译
        InvokeHelper.Register(typeof(ILocalizationXEvent), LocalizationXEventConst.Translate, 1);
        InvokeHelper.Register(typeof(ILocalizationXEvent), LocalizationXEventConst.Translate, 2);
        //注册缓存
        InvokeHelper.Register(typeof(ILocalizationXEvent), LocalizationXEventConst.SetCache, 3);
        InvokeHelper.Register(typeof(ILocalizationXEvent), LocalizationXEventConst.GetCache, 1);
        //IStringLocalizer的GetAllStrings
        InvokeHelper.Register(typeof(ILocalizationXEvent), LocalizationXEventConst.GetAllStrings, 1);
        //LX.Register(typeof(ILocalizationXEvent), "LoadData");

        LocalizationLoadData();
    }

    /// <summary>
    ///     本地化加载数据/刷新数据
    /// </summary>
    public static void LocalizationLoadData()
    {
        AppX.TaskDelay(() =>
        {
            try
            {
                InvokeHelper.Execute(typeof(ILocalizationXEvent), LocalizationXEventConst.LoadData);
            }
            catch (Exception e)
            {
                LogX.Error($"本地化加载数据/刷新数据 LX->LocalizationLoadData：{e.ToStringEx()}", LogFloder);
            }
        }, 2 * 1000);
    }


    #region Furion

    /// <summary>
    ///     获取 String 多语言本地化实例
    /// </summary>
    public static IStringLocalizer? Text => App.GetService<IStringLocalizerFactory>(App.RootServices)?.Create();

    /// <summary>
    ///     获取 Html 多语言本地化实例
    /// </summary>
    public static IHtmlLocalizer? Html => App.GetService<IHtmlLocalizerFactory>(App.RootServices)?.Create();

    /// <summary>
    ///     获取特定类型的 String 多语言本地化实例
    /// </summary>
    /// <typeparam name="T">特定类型</typeparam>
    /// <returns>
    ///     <see cref="IStringLocalizer{T}" />
    /// </returns>
    public static IStringLocalizer<T> TextOf<T>()
    {
        return L.TextOf<T>();
    }

    /// <summary>
    ///     获取特定类型的 Html 多语言本地化实例
    /// </summary>
    /// <typeparam name="T">特定类型</typeparam>
    /// <returns>
    ///     <see cref="IHtmlLocalizer{T}" />
    /// </returns>
    public static IHtmlLocalizer<T> HtmlOf<T>()
    {
        return L.HtmlOf<T>();
    }

    /// <summary>
    ///     设置当前选择的语言
    /// </summary>
    /// <param name="culture"></param>
    /// <param name="immediately">是否立即对当前线程有效，设置 true 表示立即有效，默认情况下只会影响下一次请求</param>
    public static void SetCulture(string culture, bool immediately = false)
    {
        L.SetCulture(culture, immediately);
    }

    /// <summary>
    ///     获取当前选择的语言
    /// </summary>
    /// <returns></returns>
    public static RequestCulture GetSelectCulture()
    {
        return L.GetSelectCulture();
    }

    /// <summary>
    ///     设置当前线程 UI 区域性
    /// </summary>
    /// <param name="culture"></param>
    /// <remarks>对当前线程（代码）立即有效</remarks>
    /// <returns></returns>
    public static void SetCurrentUICulture(string culture)
    {
        L.SetCurrentUICulture(culture);
    }

    /// <summary>
    ///     获取当前线程 UI 区域性
    /// </summary>
    /// <returns></returns>
    public static CultureInfo GetCurrentUICulture()
    {
        return L.GetCurrentUICulture();
    }

    /// <summary>
    ///     获取系统提供的语言列表
    /// </summary>
    /// <returns></returns>
    public static Dictionary<string, string> GetCultures()
    {
        return L.GetCultures();
    }

    /// <summary>
    ///     根据实体类属性名获取对应的多语言配置
    /// </summary>
    /// <typeparam name="TResource">通常命名为 SharedResource </typeparam>
    /// <param name="propertyExpression">属性表达式</param>
    /// <returns></returns>
    public static LocalizedString GetString<TResource>(Expression<Func<TResource, string>> propertyExpression)
    {
        return L.GetString(propertyExpression);
    }

    /// <summary>
    ///     获取指定区域的翻译
    /// </summary>
    /// <param name="name"></param>
    /// <param name="culture"></param>
    /// <returns></returns>
    public static LocalizedString GetString(string name, string culture)
    {
        return L.GetString(name, culture);
    }

    /// <summary>
    ///     获取本地配置默认语言
    /// </summary>
    /// <returns></returns>
    public static CultureInfo GetDefaultCulture()
    {
        return L.GetDefaultCulture();
    }

    #endregion
}